package com.eagle.view.widget;

import android.app.Activity;
import android.content.Context;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.opengl.GLSurfaceView;
import android.os.Build;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

import com.eagle.support.common.CameraDataCallback;
import com.eagle.support.utils.Utils;
import com.eagle.support.utils.YuvRender;

import java.io.IOException;
import java.util.List;

/**
 * Created by Administrator on 2016/12/28.
 */
public class CameraTextureView extends TextureView implements TextureView.SurfaceTextureListener {
    public static final String TAG = "CameraTextureView";
    private static final int kScreenOrientationPortrait = 0;
    private static final int kScreenOrientationLand = 1;
    Context mContext;
    private boolean mIsPreviewing;
    private boolean mIsAutoFocus = true;
    private int mCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
    private Camera mCamera;
    private int mOrientation = 90;
    private int mOri = CameraTextureView.kScreenOrientationPortrait;
    private SurfaceTexture mSurfaceTexture;
    private int mPreviewWidth = 320;
    private int mPreviewHeight = 240;
    private CameraDataCallback mDataCallback;

    private int mPreviewAreaWidth, mPreviewAreaHeight;

    public CameraTextureView(Context context) {
        super(context);
        setSurfaceTextureListener(this);
    }

    public void setDataCallback(CameraDataCallback dataCallback) {
        mDataCallback = dataCallback;
    }

    public CameraTextureView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        mPreviewAreaHeight = attrs.getAttributeResourceValue(null, "width", 300);
        mPreviewAreaWidth = attrs.getAttributeResourceValue(null, "height", 300);
        Log.d(TAG, mPreviewAreaWidth + "*" + mPreviewAreaHeight);
        setSurfaceTextureListener(this);
    }

    public CameraTextureView(Context context, int width, int height) {
        super(context);
        mContext = context;
        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(width, height);
        setLayoutParams(lp);
        mPreviewAreaHeight = height;
        mPreviewAreaWidth = width;
        setSurfaceTextureListener(this);
    }

    public void setPreviewAreaSize(int width, int height) {
        Log.d(TAG, "setPreviewAreaSize:" + width + "*" + height);
        mPreviewAreaHeight = height;
        mPreviewAreaWidth = width;
    }

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        try {
            mSurfaceTexture = surface;

            if (Build.VERSION.SDK_INT < 9) {
                mCamera = Camera.open();
            } else {
                mCamera = Camera.open(mCameraId);
            }
            startCameraPreview(surface);
        } catch (Exception e) {
            Log.e(TAG, "onSurfaceTextureAvailable: " + e.toString());
        }
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {

    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        destroyCamera();
        return true;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {

    }

    private void setFocusContinuousMode(Camera.Parameters parameters) {
        if (Build.VERSION.SDK_INT < 9) {
            return;
        }
        List<String> supportedFocus = parameters.getSupportedFocusModes();
        if (CameraSetting.isSupported(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO, supportedFocus)) {
            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
        }
    }

    public void changeCamera() {
        if (Build.VERSION.SDK_INT < 9) {
            return;
        }

        if (mCameraId == Camera.CameraInfo.CAMERA_FACING_BACK) {
            mCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;
        } else {
            mCameraId = Camera.CameraInfo.CAMERA_FACING_BACK;
        }
        destroyCamera();
        mCamera = Camera.open(mCameraId);

        startCameraPreview(mSurfaceTexture);
    }

    private Camera.PreviewCallback mCameraPreviewCallback = new Camera.PreviewCallback() {

        @Override
        public void onPreviewFrame(byte[] arg0, Camera arg1) {
            if (mDataCallback != null) {
                mDataCallback.onCameraData(arg0, arg1);
                mCamera.addCallbackBuffer(arg0);
            }
        }
    };

    private void setCameraParameter() {
        try {
            Camera.Parameters parameters = mCamera.getParameters();
            parameters.setPreviewSize(mPreviewWidth, mPreviewHeight);
            if (mIsAutoFocus) {
                setFocusContinuousMode(parameters);
            }
            mCamera.setParameters(parameters);
        } catch (Exception e) {

        }
    }

    private void startCameraPreview(SurfaceTexture surface) {
        mIsPreviewing = false;

        setCameraParameter();

        mCamera.addCallbackBuffer(new byte[mPreviewWidth * mPreviewHeight * 3 / 2]);
        mCamera.setPreviewCallbackWithBuffer(mCameraPreviewCallback);

        int displayRotation = CameraSetting.getDisplayRotation((Activity) mContext);
        mOrientation = CameraSetting.getDisplayOrientation(displayRotation, mCameraId);
        if (mOri == CameraTextureView.kScreenOrientationPortrait) {
            mCamera.setDisplayOrientation(mOrientation);
        }
        try {
            mCamera.setPreviewTexture(surface);
        } catch (IOException e) {
            destroyCamera();
        }

        mCamera.startPreview();
        mIsPreviewing = true;
    }

    public void destroyCamera() {
        if (mCamera != null) {
            mCamera.setPreviewCallbackWithBuffer(null);
            if (mIsPreviewing) {
                mCamera.stopPreview();
                mIsPreviewing = false;
            }
            mCamera.release();
            mCamera = null;
        }
    }

    public int getCameraId() {
        return mCameraId;
    }
}
